home *** CD-ROM | disk | FTP | other *** search
/ PC World 2008 September / PCWorld_2008-09_cd.bin / v cisle / sadanastroju / greasemonkey-0.8.20080609.0-fx.xpi / chrome / greasemonkey.jar / chromeFiles / content / xmlhttprequester.js < prev   
Text File  |  2008-06-09  |  4KB  |  119 lines

  1. function GM_xmlhttpRequester(unsafeContentWin, chromeWindow) {
  2.   this.unsafeContentWin = unsafeContentWin;
  3.   this.chromeWindow = chromeWindow;
  4. }
  5.  
  6. // this function gets called by user scripts in content security scope to
  7. // start a cross-domain xmlhttp request.
  8. //
  9. // details should look like:
  10. // {method,url,onload,onerror,onreadystatechange,headers,data}
  11. // headers should be in the form {name:value,name:value,etc}
  12. // can't support mimetype because i think it's only used for forcing
  13. // text/xml and we can't support that
  14. GM_xmlhttpRequester.prototype.contentStartRequest = function(details) {
  15.   if (!GM_apiLeakCheck("GM_xmlhttpRequest")) {
  16.     return;
  17.   }
  18.  
  19.   // don't actually need the timer functionality, but this pops it
  20.   // out into chromeWindow's thread so that we get that security
  21.   // context.
  22.   GM_log("> GM_xmlhttpRequest.contentStartRequest");
  23.  
  24.   // important to store this locally so that content cannot trick us up with
  25.   // a fancy getter that checks the number of times it has been accessed,
  26.   // returning a dangerous URL the time that we actually use it.
  27.   var url = details.url;
  28.  
  29.   // make sure that we have an actual string so that we can't be fooled with
  30.   // tricky toString() implementations.
  31.   if (typeof url != "string") {
  32.     throw new Error("Invalid url: url must be of type string");
  33.   }
  34.  
  35.   var ioService = Components.classes["@mozilla.org/network/io-service;1"]
  36.                   .getService(Components.interfaces.nsIIOService);
  37.   var scheme = ioService.extractScheme(url);
  38.  
  39.   // This is important - without it, GM_xmlhttpRequest can be used to get
  40.   // access to things like files and chrome. Careful.
  41.   switch (scheme) {
  42.     case "http":
  43.     case "https":
  44.     case "ftp":
  45.       this.chromeWindow.setTimeout(
  46.         GM_hitch(this, "chromeStartRequest", url, details), 0);
  47.       break;
  48.     default:
  49.       throw new Error("Invalid url: " + url);
  50.   }
  51.  
  52.   GM_log("< GM_xmlhttpRequest.contentStartRequest");
  53. };
  54.  
  55. // this function is intended to be called in chrome's security context, so
  56. // that it can access other domains without security warning
  57. GM_xmlhttpRequester.prototype.chromeStartRequest = function(safeUrl, details) {
  58.   GM_log("> GM_xmlhttpRequest.chromeStartRequest");
  59.   var req = new this.chromeWindow.XMLHttpRequest();
  60.  
  61.   this.setupRequestEvent(this.unsafeContentWin, req, "onload", details);
  62.   this.setupRequestEvent(this.unsafeContentWin, req, "onerror", details);
  63.   this.setupRequestEvent(this.unsafeContentWin, req, "onreadystatechange",
  64.                          details);
  65.  
  66.   req.open(details.method, safeUrl);
  67.  
  68.   if (details.overrideMimeType) {
  69.     req.overrideMimeType(details.overrideMimeType);
  70.   }
  71.  
  72.   if (details.headers) {
  73.     for (var prop in details.headers) {
  74.       req.setRequestHeader(prop, details.headers[prop]);
  75.     }
  76.   }
  77.  
  78.   req.send((details.data) ? details.data : null);
  79.   GM_log("< GM_xmlhttpRequest.chromeStartRequest");
  80. }
  81.  
  82. // arranges for the specified 'event' on xmlhttprequest 'req' to call the
  83. // method by the same name which is a property of 'details' in the content
  84. // window's security context.
  85. GM_xmlhttpRequester.prototype.setupRequestEvent =
  86. function(unsafeContentWin, req, event, details) {
  87.   GM_log("> GM_xmlhttpRequester.setupRequestEvent");
  88.  
  89.   if (details[event]) {
  90.     req[event] = function() {
  91.       GM_log("> GM_xmlhttpRequester -- callback for " + event);
  92.  
  93.       var responseState = {
  94.         // can't support responseXML because security won't
  95.         // let the browser call properties on it
  96.         responseText:req.responseText,
  97.         readyState:req.readyState,
  98.         responseHeaders:(req.readyState == 4 ?
  99.                          req.getAllResponseHeaders() :
  100.                          ""),
  101.         status:(req.readyState == 4 ? req.status : 0),
  102.         statusText:(req.readyState == 4 ? req.statusText : ""),
  103.         finalUrl:(req.readyState == 4 ? req.channel.URI.spec : "")
  104.       }
  105.  
  106.       // Pop back onto browser thread and call event handler.
  107.       // Have to use nested function here instead of GM_hitch because
  108.       // otherwise details[event].apply can point to window.setTimeout, which
  109.       // can be abused to get increased priveledges.
  110.       new XPCNativeWrapper(unsafeContentWin, "setTimeout()")
  111.         .setTimeout(function(){details[event](responseState);}, 0);
  112.  
  113.       GM_log("< GM_xmlhttpRequester -- callback for " + event);
  114.     }
  115.   }
  116.  
  117.   GM_log("< GM_xmlhttpRequester.setupRequestEvent");
  118. };
  119.